package com.hejx.security.web.interceptor;

import com.hejx.security.common.utils.ColUtil;
import com.hejx.security.dto.OnlineUser;
import com.hejx.security.pojo.Resource;
import com.hejx.security.pojo.Role;
import com.hejx.security.web.annotation.hasAnyRoles;
import com.hejx.security.web.annotation.hasPermission;
import com.hejx.security.web.annotation.hasRole;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Created by 追风少年
 * 权限拦截器
 * @email doubihah@foxmail.com
 * @create 2017/12/27 11:05
 **/
public class SecurityInterceptor extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(SecurityInterceptor.class);

    /**
     * 在业务处理器处理请求之前被调用
     * 如果返回false
     * 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链
     * 如果返回true
     * 执行下一个拦截器,直到所有的拦截器都执行完毕
     * 再执行被拦截的Controller
     * 然后进入拦截器链,
     * 从最后一个拦截器往回执行所有的postHandle()
     * 接着再从最后一个拦截器往回执行所有的afterCompletion()
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag = true;
        OnlineUser onlineUser = null;
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            onlineUser = (OnlineUser) request.getSession().getAttribute("user");
            hasRole hasRole = handlerMethod.getMethodAnnotation(hasRole.class);
            if(hasRole != null){ // 需要验证角色
                flag = false;
                if(this.checkRole(onlineUser,hasRole)) return true;
            }
            hasAnyRoles hasAnyRoles = handlerMethod.getMethodAnnotation(hasAnyRoles.class);
            if(hasAnyRoles != null){
                flag = false;
                if(this.checkRole(onlineUser,hasAnyRoles)) return true;
            }
            hasPermission hasPermission = handlerMethod.getMethodAnnotation(hasPermission.class);
            if(hasPermission != null){
                flag = false;
                if(this.checkPermission(onlineUser,hasPermission)) return true;
            }
        }
        if(!flag){ // 没有权限
//             String requestUri = request.getRequestURI();
        String contextPath = request.getContextPath();
//        String url = requestUri.substring(contextPath.length());
            if(onlineUser == null){
                logger.debug("游客用户访问资源:{},失败！,没有权限访问",contextPath);
            }else{
                logger.debug("用户[{}]访问资源:{},失败！,没有权限访问",onlineUser.getUsername(),contextPath);
            }
            response.sendRedirect("/error/403");
            return false;
        }
        return true;
    }

    /**
     * 检查用户是否具有指定角色
     * @return
     */
    private boolean checkRole(OnlineUser user, hasRole hasRole){
        String roleName = hasRole.name();
        if(user == null || ColUtil.isEmpty(user.getRoles())) return false;
        for (int i = 0; i < user.getRoles().size(); i++) {
            Role role = user.getRoles().get(i);
            if(roleName.equals(role.getRole())){
                return true;
            }
        }
        return false;
    }

    /**
     * 验证当前用户是否拥有以下任意一个角色
     */
    private boolean checkRole(OnlineUser user, hasAnyRoles hasAnyRoles){
        if(user == null || ColUtil.isEmpty(user.getRoles())) return false;
        String roles_str = hasAnyRoles.roles();
        for (int i = 0; i < user.getRoles().size(); i++) {
            Role role = user.getRoles().get(i);
            if(roles_str.indexOf(role.getRole()) != -1){
                return true;
            }
        }
        return false;
    }

    /**
     * 验证当前用户是否拥有指定权限
     */
    private boolean checkPermission(OnlineUser user, hasPermission hasPermission){
        if(user == null || ColUtil.isEmpty(user.getRoles())) return false;
        String permission = hasPermission.permission();
        for (int i = 0; i < user.getResources().size(); i++) {
            Resource resource = user.getResources().get(i);
            if(permission.equals(resource.getPermission())){
                return true;
            }
        }
        return false;
    }



}
